package com.betterjr.modules.accountSupervision.service;

import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.betterjr.common.selectkey.SerialGenerator;
import com.betterjr.common.service.BaseService;
import com.betterjr.common.utils.BTAssert;
import com.betterjr.mapper.pagehelper.Page;
import com.betterjr.modules.accountSupervision.dao.ScfWarnMapper;
import com.betterjr.modules.accountSupervision.entity.ScfAccBalBean;
import com.betterjr.modules.accountSupervision.entity.ScfAccDtlBean;
import com.betterjr.modules.accountSupervision.entity.ScfWarnBean;
import com.betterjr.modules.accountSupervision.utils.ScfRomoteUtil;
import com.betterjr.modules.risk.loanmanage.entity.PaymentPlan;
import com.betterjr.modules.risk.loanmanage.service.PaymentPlanService;

/**
 * 异常事件
 */
@Service
public class ScfWarnService extends BaseService<ScfWarnMapper, ScfWarnBean> {

    @Autowired
    private ScfAccBalService scfAccBalService;
    @Autowired
    private ScfAccDtlService scfAccDtlService;
    @Autowired
    private PaymentPlanService paymentPlanService;
    @Autowired
    private ScfExceptionService scfExceptionService;
    @Autowired
    private ScfRepaymentService scfRepaymentService;

    /**
     * 异常事件（余额预警）
     * @param anMap
     * @param anPageNum
     * @param anPageSize
     * @return
     * @throws ParseException
     */
    public Page<ScfWarnBean> queryBalanceWarnList(final Map<String, Object> anMap, final int anPageNum,
            final int anPageSize) throws ParseException {

        Page<ScfWarnBean> page = new Page<>();
        final Calendar calendar = Calendar.getInstance();
        final Date newDate = new Date(System.currentTimeMillis());
        calendar.setTime(newDate);
        calendar.add(Calendar.DAY_OF_YEAR, 7);
        final Date t = calendar.getTime();
        final SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
        final String date = formatter.format(t);
        anMap.put("endDate", date);
        anMap.put("beginDate", new Date());
        final List<ScfWarnBean> Templist = this.mapper.getList(anMap);
        final List<ScfWarnBean> list = new ArrayList<>();
        final List<ScfWarnBean> pageList = new ArrayList<>();
        for (final ScfWarnBean bean : Templist) {
            BigDecimal bal = BigDecimal.ZERO;
            BigDecimal availBal = BigDecimal.ZERO;
            // final Map<String, Object> datas = new HashMap<>();
            // Map<String, Object> result = new HashMap<>();
            // datas.put("accountCode",bean.getPayAccountNo());
            // datas.put("supplierId",bean.getSupplierId());
            // result = ScfRomoteUtil.callService("QueryCurBalCpf", datas, ScfRomoteUtil.CONSTANT_QUERY_BALANCE_WSDL);
            // if(result.get("data") != null){
            // List<Map<String, String>> mapList = (List<Map<String, String>>)result.get("data");
            // if(null != mapList.get(0).get("remainMoney") && !"".equals(mapList.get(0).get("remainMoney")))
            // bal = new BigDecimal(mapList.get(0).get("remainMoney"));
            // if(null != mapList.get(0).get("usableMoney") && !"".equals(mapList.get(0).get("usableMoney")))
            // availBal = new BigDecimal(mapList.get(0).get("usableMoney"));
            // }
            final Map<String, BigDecimal> balMap = this.findBal(bean.getPayAccountNo(), bean.getSupplierId());
            bal = balMap.get("bal");
            availBal = balMap.get("availBal");
            if (bean.getCutpaymentMoney().compareTo(availBal) > 0) {
                bean.setBalance(bal);
                bean.setAvailableBalance(availBal);
                calendar.setTime(formatter.parse(bean.getCutpaymentDate()));
                calendar.add(Calendar.DAY_OF_YEAR, -7);
                bean.setWarnDate(formatter.format(calendar.getTime()));
                list.add(bean);
            }
        }
        /**
         * 分页处理
         */
        final int begin = (anPageNum - 1) * anPageSize;
        int end = anPageNum * anPageSize + 1;
        if (end > list.size()) {
            end = list.size();
        }
        for (int i = begin; i < end; i++) {
            pageList.add(list.get(i));
        }
        page = Page.listToPage(pageList);
        page.setPageNum(anPageNum);
        page.setPageSize(anPageSize);
        page.setTotal(list.size());
        return page;
    }

    /**
     * 异常事件（余额预警）查询数量
     * @return
     */
    public int queryBalanceWarnCount(final Map<String, Object> anMap) {
        int count = 0;
        final Calendar calendar = Calendar.getInstance();
        final Date newDate = new Date(System.currentTimeMillis());
        calendar.setTime(newDate);
        calendar.add(Calendar.DAY_OF_YEAR, 7);
        final Date t = calendar.getTime();
        final SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
        final String date = formatter.format(t);
        anMap.put("endDate", date);
        anMap.put("beginDate", new Date());
        final List<ScfWarnBean> templist = this.mapper.getList(anMap);
        count = templist.size();
        return count;
    }

    /**
     * 异常事件（本金预警）
     * @param anMap
     * @param anPageNum
     * @param anPageSize
     * @return
     */
    public Page<ScfWarnBean> queryCapitalWarnList(final Map<String, Object> anMap, final int anPageNum,
            final int anPageSize) {
        Page<ScfWarnBean> page = new Page<>();
        final Map<String, Object> map = this.mapper.getCapitalCount(anMap);
        final Long count = (Long) map.get("num");
        final int start = (anPageNum - 1) * anPageSize;
        anMap.put("start", start);
        anMap.put("anPageSize", anPageSize);
        page = Page.listToPage(this.mapper.getCapitalList(anMap));
        page.setPageNum(anPageNum);
        page.setPageSize(anPageSize);
        page.setTotal(count);
        return page;
    }

    /**
     * 异常事件（本金预警）数量
     * @return
     */
    public int queryCapitalWarnCount(final Map<String, Object> anMap) {
        int count = 0;
   		Map<String,Object> map = this.mapper.getCapitalCount(anMap);
        count = ((Long) map.get("num")).intValue();
        return count;
    }

    /**
     * 定时任务查询余额
     */
    public void aotoBal() {
        final Map<String, Object> anMap = new HashMap<>();
        final Calendar calendar = Calendar.getInstance();
        final Date newDate = new Date(System.currentTimeMillis());
        calendar.setTime(newDate);
        calendar.add(Calendar.DAY_OF_YEAR, 7);
        final Date t = calendar.getTime();
        final SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
        final String date = formatter.format(t);
        anMap.put("endDate", date);
        anMap.put("beginDate", new Date());
        final List<ScfWarnBean> Templist = this.mapper.getList(anMap);
        for (final ScfWarnBean bean : Templist) {
            final Map<String, Object> datas = new HashMap<>();
            Map<String, Object> result = new HashMap<>();
            datas.put("accountCode", bean.getPayAccountNo());
            datas.put("supplierId", bean.getSupplierId());
            result = ScfRomoteUtil.callService("QueryCurBalCpf", datas, ScfRomoteUtil.CONSTANT_QUERY_BALANCE_WSDL);
            BigDecimal bal = BigDecimal.ZERO;
            BigDecimal availBal = BigDecimal.ZERO;
            // 查询当天是否有余额。有则更新没有则插入
            final Map<String, Object> queryMap = new HashMap<>();
            queryMap.put("accountNo", bean.getPayAccountNo());
            queryMap.put("balDate", formatter.format(newDate));
            final List<ScfAccBalBean> balList = scfAccBalService.queryAccBalList(queryMap);
            if (result != null && result.get("data") != null) {
                final List<Map<String, String>> mapList = (List<Map<String, String>>) result.get("data");
                if (null != mapList.get(0).get("remainMoney") && !"".equals(mapList.get(0).get("remainMoney")))
                    bal = new BigDecimal(mapList.get(0).get("remainMoney"));
                if (null != mapList.get(0).get("usableMoney") && !"".equals(mapList.get(0).get("usableMoney")))
                    availBal = new BigDecimal(mapList.get(0).get("usableMoney"));
                final Map<String, Object> map = new HashMap<>();
                map.put("availBalance", availBal);
                map.put("balDate", formatter.format(newDate));
                map.put("balance", bal);
                map.put("msgCode", mapList.get(0).get("returnCode"));
                map.put("returnMsg", mapList.get(0).get("returntMsg"));
                map.put("accountNo", bean.getPayAccountNo());
                if (balList != null && balList.size() > 0) {
                    map.put("id", balList.get(0).getId());
                    scfAccBalService.toUpdateAccBal(map);
                } else {
                    map.put("id", SerialGenerator.getLongValue(ScfAccBalBean.selectKey));
                    scfAccBalService.addAccBal(map);
                }
                // 如果查询余额有异常则插入数据到异常交易表
                if (!"".equals(mapList.get(0).get("errorCode"))) {
                    final Map<String, Object> insertMap = new HashMap<>();
                    insertMap.put("loanId", bean.getId());
                    insertMap.put("supplierName", bean.getSupplierName());
                    insertMap.put("supplierNo", bean.getSupplierNo());
                    insertMap.put("accountNo", bean.getPayAccountNo());
                    insertMap.put("warnDate", mapList.get(0).get("errorTime"));
                    insertMap.put("information", mapList.get(0).get("errorInfo"));
                    insertMap.put("id", SerialGenerator.getLongValue(ScfWarnBean.exceptionWarnSelectKey));
                    scfExceptionService.addExceptionWarn(insertMap);
                }
            }
        }
    }

    /**
     * 定时任务扫描明细
     */
    public void aotoDtl() {
        final Map<String, Object> anMap = new HashMap<>();
        final Calendar calendar = Calendar.getInstance();
        final Date newDate = new Date(System.currentTimeMillis());
        calendar.setTime(newDate);
        calendar.add(Calendar.DAY_OF_YEAR, 3);// 监听3天的记录
        final Date t = calendar.getTime();
        final SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
        final String date = formatter.format(t);
        anMap.put("endDate", date);
        anMap.put("beginDate", new Date());
        final List<ScfWarnBean> list = this.mapper.getList(anMap);
        for (final ScfWarnBean bean : list) {
            // 通过接口获取值
            final Map<String, Object> datas = new HashMap<>();
            Map<String, Object> result = new HashMap<>();
            datas.put("accountCode", bean.getPayAccountNo());
            datas.put("supplierId", bean.getSupplierId());
            datas.put("startDate", formatter.format(new Date()));
            datas.put("endDate", formatter.format(new Date()));
            result = ScfRomoteUtil.callService("QueryHisDtlCpf", datas, ScfRomoteUtil.CONSTANT_QUERY_DTL_WSDL);
            BigDecimal bal = BigDecimal.ZERO;
            BigDecimal tradeMoney = BigDecimal.ZERO;
            if (result != null && result.get("data") != null) {
                final List<Map<String, String>> mapList = (List<Map<String, String>>) result.get("data");
                for (int i = 0; i < mapList.size(); i++) {
                    final ScfAccDtlBean dtl = new ScfAccDtlBean();
                    if (null != mapList.get(i).get("remainMoney") && !"".equals(mapList.get(i).get("remainMoney")))
                        bal = new BigDecimal(mapList.get(i).get("remainMoney"));
                    if (null != mapList.get(i).get("tradeMoney") && !"".equals(mapList.get(i).get("tradeMoney")))
                        tradeMoney = new BigDecimal(mapList.get(i).get("tradeMoney"));
                    // 查询是否存在这笔明细
                    dtl.setTransTime(mapList.get(i).get("tradeTime"));
                    final Map<String, Object> queryMap = new HashMap<>();
                    queryMap.put("bankAcc", bean.getPayAccountNo());
                    queryMap.put("transTime", dtl.getTransTime());
                    final List<ScfAccDtlBean> dtlList = scfAccDtlService.queryAccDtlList(queryMap);
                    if (null == dtlList || dtlList.size() == 0) {
                        dtl.setId(SerialGenerator.getLongValue(ScfAccDtlBean.selectKey));
                        dtl.setBankAcc(mapList.get(i).get("accountCode"));
                        dtl.setAccName(mapList.get(i).get("accountName"));
                        dtl.setBankName(mapList.get(i).get("bankName"));
                        dtl.setOppAcc(mapList.get(i).get("otherAccount"));
                        dtl.setOppAccName(mapList.get(i).get("otherName"));
                        dtl.setOppBankName(mapList.get(i).get("otherDeposit"));
                        // dtl.setTransTime(mapList.get(i).get("tradeTime"));
                        dtl.setAmt(tradeMoney);
                        dtl.setBalance(bal);
                        dtl.setRemark(mapList.get(i).get("tradeSummary"));
                        dtl.setUses(mapList.get(i).get("postScript"));
                        dtl.setSign(mapList.get(i).get("tradeSign"));// 1支出0收入
                        scfAccDtlService.addAccDtl(dtl);
                        if ("1".equals(dtl.getSign())) {// 如果是支出则插入异常交易表
                            final Map<String, Object> insertMap = new HashMap<>();
                            insertMap.put("loanId", bean.getId());
                            insertMap.put("supplierName", bean.getSupplierName());
                            insertMap.put("supplierNo", bean.getSupplierNo());
                            insertMap.put("transactionAmount", dtl.getAmt());
                            insertMap.put("transactionDate", dtl.getTransTime());
                            insertMap.put("accountNo", dtl.getBankAcc());
                            insertMap.put("availableBalance", bal);
                            insertMap.put("balance", bal);
                            insertMap.put("warnDate", new Date());
                            insertMap.put("information", "");
                            insertMap.put("id", SerialGenerator.getLongValue(ScfWarnBean.exceptionWarnSelectKey));
                            scfExceptionService.addExceptionWarn(insertMap);
                        }
                    }
                }
            }

        }
    }

    /**
     * 还款计划扣款结果处理
     * @param planId
     * @param planData
     */
    public void writeBackPlanData(final String planId, final List<Map<String, String>> planData) {
        final PaymentPlan paymentPlan = paymentPlanService.selectByPrimaryKey(Long.parseLong(planId));
        BTAssert.notNull(paymentPlan, "查询不到计划信息！");
        final List<Map<String, String>> validDatas = filterValidDatas(planData);
        final Map<String, Object> warnMap = new HashMap<>();
        warnMap.put("id", paymentPlan.getLoanDataId());
        final ScfWarnBean scfWarnBean = this.mapper.getLoanDate(warnMap);
        for (final Map<String, String> paymentMapData : validDatas) {
            BigDecimal bal = BigDecimal.ZERO;
            BigDecimal availBal = BigDecimal.ZERO;
            final Map<String, BigDecimal> balMap = this.findBal(scfWarnBean.getPayAccountNo(),
                    scfWarnBean.getSupplierId());
            bal = balMap.get("bal");
            availBal = balMap.get("availBal");
            final Map<String, Object> insertMap = new HashMap<>();
            insertMap.put("loanId", scfWarnBean.getId());
            insertMap.put("supplierName", scfWarnBean.getSupplierName());
            insertMap.put("supplierNo", scfWarnBean.getSupplierNo());
            insertMap.put("cutpaymentMoney", scfWarnBean.getCutpaymentMoney());
            insertMap.put("cutpaymentDate", scfWarnBean.getCutpaymentDate());
            insertMap.put("payAccountNo", scfWarnBean.getPayAccountNo());
            insertMap.put("availableBalance", availBal);
            insertMap.put("balance", bal);
            insertMap.put("warnDate", new Date());
            insertMap.put("id", SerialGenerator.getLongValue(ScfWarnBean.capitalWarnSelectKey));
            this.mapper.addCapitalWarn(insertMap);
        }
    }

    /**
     * 筛选扣款失败的记录
     * @param planData
     * @return
     */
    private List<Map<String, String>> filterValidDatas(final List<Map<String, String>> planData) {
        final List<Map<String, String>> validDatas = new ArrayList<>();
        for (final Map<String, String> map : planData) {
            // 状态 云资金对应 ----100 扣款成功 ; 70 等待结果; 90 扣款失败; 95 交易异常; 99 扣款部分成功; 60 等待发送;
            if ("90".equals(map.get("status")) || "95".equals(map.get("status"))) {
                // 设置成本地对应状态码
                validDatas.add(map);
            }
        }
        return validDatas;
    }

    /**
     * 调用接口查询余额
     * @param accountNo
     * @param supplierId
     * @return
     */
    private Map<String, BigDecimal> findBal(final String accountNo, final String supplierId) {
        final Map<String, Object> datas = new HashMap<>();
        final Map<String, BigDecimal> map = new HashMap<>();
        Map<String, Object> result = new HashMap<>();
        datas.put("accountCode", accountNo);
        datas.put("supplierId", supplierId);
        result = ScfRomoteUtil.callService("QueryCurBalCpf", datas, ScfRomoteUtil.CONSTANT_QUERY_BALANCE_WSDL);
        BigDecimal bal = BigDecimal.ZERO;
        BigDecimal availBal = BigDecimal.ZERO;
        if (result.get("data") != null) {
            final List<Map<String, String>> mapList = (List<Map<String, String>>) result.get("data");
            if (null != mapList.get(0).get("remainMoney") && !"".equals(mapList.get(0).get("remainMoney")))
                bal = new BigDecimal(mapList.get(0).get("remainMoney"));
            if (null != mapList.get(0).get("usableMoney") && !"".equals(mapList.get(0).get("usableMoney")))
                availBal = new BigDecimal(mapList.get(0).get("usableMoney"));
        }
        map.put("bal", bal);
        map.put("availBal", availBal);
        return map;
    }

    /**
     * 根据资金方id 查询账户监控数量
     * @param providerId
     * @return
     */
    public List<Map<String, Object>> getWarnCountByProviderId(final String providerId) {
        final List<Map<String, Object>> list = new ArrayList<>();
        int flag = 1;
        final Map<String, Object> queryMap = new HashMap<>();
        queryMap.put("providerId", providerId);
        // 查询一周内待收 数量 根据资金方id
        final int count1 = scfRepaymentService.queryCountRepayment(flag, queryMap);
        final Map<String, Object> map1 = new HashMap<>();
        map1.put("title", "一周内待收");
        map1.put("count", count1);
        list.add(map1);

        // 查询一周内待收 数量 根据资金方id
        flag = 2;
        final int count2 = scfRepaymentService.queryCountRepayment(flag, queryMap);
        final Map<String, Object> map2 = new HashMap<>();
        map1.put("title", "逾期");
        map1.put("count", count2);
        list.add(map2);

        // 余额预警 根据资金方id
        final int count3 = this.queryBalanceWarnCount(queryMap);
        final Map<String, Object> map3 = new HashMap<>();
        map1.put("title", "余额预警");
        map1.put("count", count3);
        list.add(map3);

        // 本金预警 根据资金方id
        final int count4 = this.queryCapitalWarnCount(queryMap);
        final Map<String, Object> map4 = new HashMap<>();
        map1.put("title", "本金预警");
        map1.put("count", count4);
        list.add(map4);

        // 异常交易 根据资金方id
        final int count5 = scfExceptionService.queryExceptionWarnCount(queryMap);
        final Map<String, Object> map5 = new HashMap<>();
        map1.put("title", "异常交易");
        map1.put("count", count5);
        list.add(map5);

        return list;
    }

}
